package com.linko.soundrecorder;

import android.content.Context;
import android.os.Environment;
import android.os.StatFs;
import android.os.storage.StorageManager;
import android.text.TextUtils;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class StorageHelper {
    private static final String TAG = "StorageHelper";
    private final static long VOLUME_MIN_SIZE = 30; //MB
    private static StorageHelper instance;
    private String INTERNAL_STORAGE = null;
    private String EXTERNAL_STORAGE = null;
    private Context mContext = null;
    private ArrayList<Storage> mStorages = new ArrayList<Storage>();

    public StorageHelper(Context mContext) {
        this.mContext = mContext;
    }

    public static StorageHelper getInstance(Context context) {
        if (instance == null) {
            instance = new StorageHelper(context);
        }
        instance.initStoragePaths();
        return instance;
    }

    public static boolean isVolumeMounted(String path) {
        if (TextUtils.isEmpty(path)) {
            return false;
        }
        File file = new File(path);
        if (!file.exists() && !file.canRead()) {
            return false;
        }
        SDCardInfo info = getVolumeInfo(path);
        return info.total >= VOLUME_MIN_SIZE;
    }

    public static SDCardInfo getVolumeInfo(String path) {
        SDCardInfo info = new SDCardInfo();
        try {
            android.os.StatFs statfs = new android.os.StatFs(path);

            long nBlocSize = statfs.getBlockSize();
            long nTotalBlocks = statfs.getBlockCount();
            long nAvailaBlock = statfs.getAvailableBlocks();
            long nFreeBlock = statfs.getFreeBlocks();

            info.total = nTotalBlocks * nBlocSize;
            info.free = nAvailaBlock * nBlocSize;

        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        return info;
    }


    public void initStoragePaths() {
        mStorages.clear();
        String[] paths = getVolumePaths();
        String primaryPath = Environment.getExternalStorageDirectory().getAbsolutePath();
        boolean isRemovable = Environment.isExternalStorageRemovable();
        if (isRemovable) {
            createExternalStorage(primaryPath);
            for (String path : paths) {
                if (!TextUtils.equals(path, primaryPath) && isVolumeMounted(path)) {
                    createInternalStorage(path);
                }
            }
        } else {
            createInternalStorage(primaryPath);
            for (String path : paths) {
                if (!TextUtils.equals(path, primaryPath) && isVolumeMounted(path)) {
                    createExternalStorage(path);
                }
            }
        }
    }

    public ArrayList<Storage> getStorageList() {
        return mStorages;
    }

    public ArrayList<Storage> getMountedStorageList() {
        ArrayList<Storage> storageList = getStorageList();
        ArrayList<Storage> mountedStorageList = new ArrayList<Storage>();
        for (int i = 0; i < storageList.size(); i++) {
            boolean isMounted = isVolumeMounted(storageList.get(i).mountPoint);
            if (isMounted) {
                mountedStorageList.add(storageList.get(i));
            }
        }
        return mountedStorageList;
    }

    public String getInternalSdcardPath() {
        return INTERNAL_STORAGE;
    }

    public String getExternalSdcardPath() {
        return EXTERNAL_STORAGE;
    }

    private void createExternalStorage(String path) {
        INTERNAL_STORAGE = path;
        Storage storage = new Storage();
        storage.mountPoint = path;
        storage.isPrimary = false;
        storage.descriptionId = R.string.storage_external;
        mStorages.add(storage);
    }

    private void createInternalStorage(String path) {
        EXTERNAL_STORAGE = path;
        Storage storage = new Storage();
        storage.mountPoint = path;
        storage.isPrimary = true;
        storage.descriptionId = R.string.storage_internal;
        mStorages.add(storage);
    }

    private String[] getVolumePaths() {
        StorageManager storageManager = (StorageManager) mContext
                .getSystemService(Context.STORAGE_SERVICE);
        try {
            Method method = StorageManager.class.getMethod("getVolumePaths", new Class[]{});
            method.setAccessible(true);
            Object volumePaths = method.invoke(storageManager, new Object[]{});
            if (volumePaths != null) {
                String[] paths = ((String[]) volumePaths);
                return paths;
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static class SDCardInfo {
        public long total;
        public long free;
    }

    class Storage {
        String mountPoint;
        boolean isPrimary;
        int descriptionId;
    }

    public boolean diskSpaceAvailable() {
        StatFs fs = new StatFs(SettingsActivity.getPrefStoragePath(mContext));
        // keep one free block
        return fs.getAvailableBlocks() > VOLUME_MIN_SIZE;
    }
}
